#!/usr/bin/env python

#********************************************************************
# Filename:            filterControl.py
# Authors:             Daniel Sisco
# Date Created:        10-3-2010
# 
# Abstract: This is the primary file for the FINally expense analysis tool. It is responsible for
# handling read/write access to the SQLite database as well as providing a GUI interface for the user.
#
# Copyright 2008-2010 Daniel Sisco
# This file is part of Fin-ally.
#
# Fin-ally is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Fin-ally is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fin-ally.  If not, see <http://www.gnu.org/licenses/>.
#********************************************************************

import wx
import wx.calendar as callib
import wx.grid     as gridlib
from utils import monthDict, BLANK_TERM
from grid import CustomDataTable
from database import FilterTerms, Database
from datetime import datetime
from threads import ExpenseTypeThread

#*****************************************
# NOTE: this class was generated by wxGlade
# and hand-modified to work for FINally.
#*****************************************
class CustomFilterPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        
        self.database = Database()
        self.bufferSize = (15,15)
        self.dataTable = CustomDataTable(gridlib.Grid)
        
        # values populated by controls in this panel - consumed by the application
        self.startMonth = "January"
        self.monthRange = 1
        self.searchTerm = ""
        
        self.filterTerms = FilterTerms()
        
        # create the overarcing date filter box
        self.filterSizer_staticbox = wx.StaticBox(self, -1, "date filter")
        
        # create and bind the month range control
        self.dateRangeText = wx.StaticText(self, -1, "month range", style=wx.ALIGN_CENTRE)
        self.slider = wx.Slider(self, 
                           100, # id
                           1,  # default
                           1,   # min
                           12,  # max
                           (-1, -1), # pos
                           (250, -1),# size
                           wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
        self.slider.SetTickFreq(1, 1)
        self.Bind(wx.EVT_SLIDER, self.OnMonthRange, self.slider)
        
        # this comboBox is based on monthDict, so find the current month key
        # in monthDict and use as default
        now = datetime.now()
        for key in monthDict:
            if(now.month == monthDict[key]):
                defaultMonth = key
        
        # create and bind the start month combo box
        self.startMonthText = wx.StaticText(self, -1, "start month")
        self.startDateCombo = wx.ComboBox(self, -1, value=defaultMonth, choices=list(monthDict.keys()), style=wx.CB_DROPDOWN|wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.OnMonthStart, self.startDateCombo)
        
        # create and bind the start year combo box
        self.startYearText = wx.StaticText(self, -1, "start year")
        self.startYearCombo = wx.ComboBox(self, -1, value="2010", choices=["2010", "2011"], style=wx.CB_DROPDOWN|wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.OnYearStart, self.startYearCombo)
        
        # create the overarcing search box 
        self.searchSizer_staticbox = wx.StaticBox(self, -1, "search")
        
        # create and bind the expense search widget
        self.searchText = wx.StaticText(self, -1, "search expenses", style=wx.ALIGN_CENTRE)
        # NOTE: for some reason the search control doesn't take a panel as the parent, just 'self'
        self.search = wx.SearchCtrl(self, size=(200,-1), style=wx.TE_PROCESS_ENTER)
        self.search.ShowCancelButton(1)
        self.search.ShowSearchButton(1)
        
        self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.OnSearch, self.search)
        self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel, self.search)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSearch, self.search)
            
        # create and bind the expenseType search widget
        self.searchTypeText = wx.StaticText(self, -1, "search type", style=wx.ALIGN_CENTRE)
        self.searchTypeCombo = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN|wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.OnTypeSearch, self.searchTypeCombo)
        self.ExpTypeComboUpdate()
        
        # declare local expenseType thread class and push the update function into it
        self.etThread = ExpenseTypeThread()
        self.etThread.StoreRefreshFunc(self.ExpTypeComboUpdate)
        
        self.reservedSizer_staticbox = wx.StaticBox(self, -1, " reserved")
        
        self.__do_layout()

    def __do_layout(self):
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        filterPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
        reservedSizer = wx.StaticBoxSizer(self.reservedSizer_staticbox, wx.HORIZONTAL)
        searchSizer = wx.StaticBoxSizer(self.searchSizer_staticbox, wx.HORIZONTAL)
        searchSizerRight = wx.BoxSizer(wx.VERTICAL)
        searchSizerLeft = wx.BoxSizer(wx.VERTICAL)
        filterSizer = wx.StaticBoxSizer(self.filterSizer_staticbox, wx.HORIZONTAL)
        
        filterSizerLeft = wx.BoxSizer(wx.VERTICAL)
        filterSizerLeft.Add(self.startMonthText, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        filterSizerLeft.Add(self.startDateCombo, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 15)
        filterSizer.Add(filterSizerLeft, 0, wx.ALL|wx.EXPAND, 5)
        
        filterSizerMid = wx.BoxSizer(wx.VERTICAL)
        filterSizerMid.Add(self.startYearText, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        filterSizerMid.Add(self.startYearCombo, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 15)
        filterSizer.Add(filterSizerMid, 0, wx.ALL|wx.EXPAND, 5)
        
        filterSizerRight = wx.BoxSizer(wx.VERTICAL)
        filterSizerRight.Add(self.dateRangeText, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        filterSizerRight.Add(self.slider, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        filterSizer.Add(filterSizerRight, 1, wx.ALL|wx.EXPAND, 5)
        
        filterPanelSizer.Add(filterSizer, 1, wx.RIGHT|wx.EXPAND, 5)
        
        searchSizerLeft.Add(self.searchText, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        searchSizerLeft.Add(self.search, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 20)
        searchSizer.Add(searchSizerLeft, 0, wx.ALL|wx.EXPAND, 5)
        
        searchSizerRight.Add(self.searchTypeText, 0, wx.ALIGN_CENTER_HORIZONTAL, 5)
        searchSizerRight.Add(self.searchTypeCombo, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 20)
        searchSizer.Add(searchSizerRight, 0, wx.ALL|wx.EXPAND, 5)
        
        filterPanelSizer.Add(searchSizer, 0, wx.EXPAND, 0)
        
        filterPanelSizer.Add(reservedSizer, 1, wx.LEFT|wx.EXPAND, 5)
        sizer_1.Add(filterPanelSizer, 1, wx.ALL|wx.EXPAND, 5)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()
     
    def OnSearch(self, event):
        localSearch = self.search.GetValue()
        
        # replace null match with "match anything"
        if(localSearch == ""):
            localSearch = BLANK_TERM
            
        self.filterTerms.SetSearchTerms(localSearch)
        self.dataTable.UpdateData()
        event.Skip()
        
    def OnCancel(self, event):
        self.search.SetValue("")
        self.filterTerms.SetSearchTerms(BLANK_TERM)
        self.dataTable.UpdateData()
        event.Skip()
        
    def OnMonthStart(self, event):
        self.filterTerms.SetStartMonth(monthDict[self.startDateCombo.GetValue()])
        self.dataTable.UpdateData()
        event.Skip()
        
    def OnMonthRange(self, event):
        self.filterTerms.SetMonthRange(self.slider.GetValue())
        self.dataTable.UpdateData()
        event.Skip()
        
    def OnYearStart(self, event):
        self.filterTerms.SetStartYear(int(self.startYearCombo.GetValue()))
        self.dataTable.UpdateData()
        event.Skip()
        
    def OnTypeSearch(self, event):
        self.filterTerms.SetExpenseTypeTerms(self.searchTypeCombo.GetValue())
        self.dataTable.UpdateData()
        event.Skip()
        
    def ExpTypeComboUpdate(self):
        """This function is responsible for re-loading all ComboBox values, and 
        setting the default value appropriately."""
        
        # refresh the choices
        self.expenseTypeChoices = self.database.GetExpenseTypeList()
        self.expenseTypeChoices.insert(0, "all")
        
        # remove all values from the ComboBox
        self.searchTypeCombo.Clear()
            
        # load new values into ComboBox
        for i in self.expenseTypeChoices:
            self.searchTypeCombo.Append(i)
            
        # set ComboBox default value 
        self.searchTypeCombo.SetValue("all")